package com.yao.fin.service.impl;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.poi.word.Word07Writer;
import cn.hutool.poi.word.WordUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yao.common.enums.business.fin.CourseBase;
import com.yao.common.enums.business.fin.LabelEnum;
import com.yao.common.enums.business.fin.SingleEnum;
import com.yao.common.exception.BusinessException;
import com.yao.common.helper.FileloadHelper;
import com.yao.fin.baidu.OcrSerivce;
import com.yao.fin.entity.FinancialTemplateEntity;
import com.yao.fin.entity.dto.FinancialTemplateDto;
import com.yao.fin.mapper.FinancialTemplateMapper;
import com.yao.fin.mapper.sql.FinancialTemplateWrapper;
import com.yao.fin.service.FinancialTemplateService;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 财务模版表 接口实现
 *
 * @author autoCode
 * @version 1.0.0-SNAPSHOT
 * @date 2020-04-09
 */
@Service
@Slf4j
public class FinancialTemplateServiceImpl extends ServiceImpl<FinancialTemplateMapper, FinancialTemplateDto>
    implements FinancialTemplateService {

    @Autowired
    private OcrSerivce ocrSerivce;

    public static void main(String[] args) {
        /*System.out.println("args = " + ResourceUtil.getResource(""));

        File file = FileUtil.file("word");
        Arrays.asList(file.listFiles()).stream().filter(FileUtil::isFile).forEach(System.out::println);


        String s = "ADBVasdfF";

        boolean b = StrUtil.startWithAny(s, "A", "B", "C");
        System.out.println("b = " + b);


        String res = "[阿萨德正确答案]:B";
        System.out.println("re = " + ReUtil.contains("正确答案", res));
        System.out.println("re = " + ReUtil.delPre("正确答案]:", res))*/;
        ;
        System.out.println("args = " + LabelEnum.values()[1]);
    }

    @Override
    public IPage<FinancialTemplateDto> page(Page<FinancialTemplateDto> page, FinancialTemplateDto dto) {

        Wrapper<FinancialTemplateDto> query = FinancialTemplateWrapper.withPage(dto);

        Page<FinancialTemplateDto> result = this.page(page, query);

        List<FinancialTemplateDto> collect =
            result.getRecords().stream().map(e -> e.fill()).collect(Collectors.toList());

        result.setRecords(collect);

        return result;
    }

    @Override
    public String export(FinancialTemplateDto dto, HttpServletResponse response) throws IOException {

        // 读取数据
        Wrapper<FinancialTemplateDto> query = FinancialTemplateWrapper.withPage(dto);
        List<FinancialTemplateDto> list = this.list(query);

        // 按习题时间分类 并对key进行排序
        Map<String, List<FinancialTemplateDto>> byDate =
            list.stream().collect(Collectors.groupingBy(FinancialTemplateDto::getTrainDate)).entrySet().stream()
                .sorted(Map.Entry.comparingByKey()).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
                    (oldValue, newValue) -> oldValue, LinkedHashMap::new));

        // 写word文件
        String fileName = dto.getLabel().getDesc() + dto.getBeginDate() + " - " + dto.getEndDate()
            + StrUtil.sub(UUID.fastUUID().toString(), 0, 3) + ".docx";

        File file = FileUtil.newFile(fileName);
        Word07Writer wordWrite = WordUtil.getWriter(file);

        Font font = new Font("微软雅黑", Font.BOLD, 13);
        Font varFont = new Font("微软雅黑", Font.PLAIN, 13);
        byDate.forEach((date, dayList) -> {
            wordWrite.addText(font, date);

            // 写题目
            dayList.stream().sorted(Comparator.comparing(FinancialTemplateDto::getCourse)).forEach(e -> {
                Integer course = e.getCourse();
                Integer singelFlag = e.getSingle();
                // wordWrite.addText(font,course + "、" + CourseBase.ZJEnum.getDesc(course)+"（"+
                // SingleEnum.getDesc(singelFlag)+"）");
                XWPFParagraph paragraph = wordWrite.getDoc().createParagraph();
                XWPFRun run1 = paragraph.createRun();
                run1.setBold(true);
                run1.setFontSize(13);
                run1.setFontFamily("微软雅黑");
                if (e.getLabel().equals(LabelEnum.ZJ)) {
                    run1.setText(CourseBase.ZJEnum.getDesc(course));
                } else if (e.getLabel().equals(LabelEnum.CPA)) {
                    run1.setText(CourseBase.CPAEnum.getDesc(course));
                }

                XWPFRun run2 = paragraph.createRun();
                run2.setBold(true);
                run2.setColor("FF0000");
                run2.setFontSize(13);
                run2.setFontFamily("微软雅黑");
                run2.setText("（" + SingleEnum.getDesc(singelFlag) + "）");

                List<String> questions = Arrays.asList(StrUtil.split(e.getQuestion(), "\n"));

                for (int i = 0; i < questions.size(); i++) {
                    if (i == 0) {
                        wordWrite.addText(varFont, course + "、" + questions.get(i));
                    } else {
                        wordWrite.addText(varFont, questions.get(i));
                    }
                }

            });

            wordWrite.addText(font, "\n\r");

            // 写答案
            dayList.stream().sorted(Comparator.comparing(FinancialTemplateEntity::getCourse)).forEach(e -> {

                wordWrite.addText(font, e.getCourse() + "、参考答案：", e.getAnswer().toUpperCase());
                wordWrite.addText(font, "解析：", e.getExplain());
            });

            wordWrite.addText(font, "\n\r");
            wordWrite.addText(font, "\n\r");

        });

        wordWrite.flush();
        wordWrite.close();

        // 文件下载
        FileloadHelper.download(response, new FileInputStream(file), file.getName());

        return fileName;
    }

    @Override
    public FinancialTemplateDto upload(MultipartFile file) {

        if(Objects.isNull(file)){
            throw new BusinessException("上传文件不能为空");
        }

        String result = "";
        try {
            String encodeImg = URLUtil.encode(Base64.encode(file.getBytes()), "UTF-8");
            result = ocrSerivce.general(encodeImg);
        } catch (IOException e) {
            log.error("调用baidu识图api失败. e = " + e.getMessage());
        }

        // 响应对象
        FinancialTemplateDto dto = new FinancialTemplateDto();

        // 段落数组
        if(StrUtil.isEmpty(result)){
            return dto;
        }

        JSONObject json = JSON.parseObject(result);

        // 段落数和结果数

        log.info("段落数:{} ;;; 结果数:{}",json.getInteger("paragraphs_result_num"), json.getInteger("words_result_num"));

        // 段落结果
        JSONArray paragraphs = json.getJSONArray("paragraphs_result");

        // 识别结果
        JSONArray words = json.getJSONArray("words_result");

        StringBuilder question = StrUtil.builder(), answer = StrUtil.builder(), explain = StrUtil.builder();

        for (int i = 0; i < paragraphs.size(); i++) {
            JSONArray words_result_idx = paragraphs.getJSONObject(i).getJSONArray("words_result_idx");
            int start = words_result_idx.getInteger(0).intValue();
            int end = words_result_idx.getInteger(words_result_idx.size() - 1).intValue();
            String res = get(words, start, end);
            Console.log("start: {} ;; end: {} ;; res:{}",start, end, res);

            // 记录答案解析开始的索引
            int idx = 0;
            if(ReUtil.contains("您的答案", res)){
                idx = i;
            }

            if(i ==  0|| (StrUtil.startWithAny(res, "A", "B", "C", "D", "E", "F"))){
                // 问题
                question.append(res).append("\n");
            }else if(ReUtil.contains("正确答案", res)){
                // 答案
                answer.append(ReUtil.delPre("正确答案]:", res));
            }else if(!ReUtil.contains("您的答案", res) && i >= idx){
                // 解析
                explain.append(res).append("\n");
            }
        }
        dto.setQuestion(question.toString());
        dto.setAnswer(answer.toString());
        dto.setExplain(explain.toString());

        log.info("百度识图组装数据得到的结果:{}", dto);

        return dto;
    }


    private String get(JSONArray words, int start, int end){
        StringBuilder wordBuffer = new StringBuilder();
        for (int i = start; i <= end; i++) {
            String temp = words.getJSONObject(i).getString("words");
            wordBuffer.append(temp);
        }

        return wordBuffer.toString();
    }

}